﻿package core.drawing
{
    import __AS3__.vec.*;
    import core.enum.*;
    import core.image.*;
    import flash.display.*;
    import flash.events.*;
    import flash.geom.*;

    final public class FillTool extends Tool
    {
        var px:uint;
        var soffset:Point;
        var target:BitmapData;
        var source:BitmapData;
        var ranges:Vector.<Range>;
        var pxchecked:Vector.<Boolean>;
        var aa:Number;
        var diff:int;
        var max:int;
        var cr:int;
        var cg:int;
        var cb:int;
        var a:int;
        var r:int;
        var g:int;
        var b:int;
        var ta:int;
        var tr:int;
        var tg:int;
        var tb:int;

        public function FillTool(param1:Tuyitu)
        {
            super(param1, ToolType.Fill, false);
            ctrl = ToolType.Picker;
            return;
        }// end function

        override public function Reset() : void
        {
            type.attitude.locked = Boolean(ed.canvas.layer.type != LayerType.Bitmap);
            if (AppState.OnCanvas)
            {
                ed.cursor.Set(type);
            }
            ed.options.SetTool(type);
            return;
        }// end function

        override public function MouseDown(event:MouseEvent) : void
        {
            var _loc_2:Point = null;
            if (!type.attitude.locked)
            {
                this.UpdateReferences();
                history.Prepare(Action.FillTool);
                this.target = layer.SetBitmapEditMode(options.opacity, new Rectangle(0, 0, canvas.dw, canvas.dh));
                options.color = ed.toolbar.GetColor(1, layer.editMask);
                this.source = options.all ? (canvas.screenshot) : (layer.bitmap.bitmapData);
                this.soffset = options.all ? (new Point(0, 0)) : (new Point(layer.x, layer.y));
                _loc_2 = canvas.GetMousePosition();
                if (_loc_2.x >= 0 && _loc_2.y >= 0 && _loc_2.x < this.target.width && _loc_2.y < this.target.height)
                {
                    if (selection == null || selection.IsSelected(_loc_2.x, _loc_2.y))
                    {
                        if (this.source != null)
                        {
                            this.px = this.source.getPixel32(_loc_2.x - this.soffset.x, _loc_2.y - this.soffset.y);
                            this.ta = this.px >>> 24 & 255;
                            this.tr = this.px >>> 16 & 255;
                            this.tg = this.px >>> 8 & 255;
                            this.tb = this.px & 255;
                            if (!options.contiguous)
                            {
                                this.FillAll();
                            }
                            else
                            {
                                this.FloodFill(_loc_2.x, _loc_2.y);
                            }
                        }
                        else
                        {
                            this.target.fillRect(this.target.rect, options.color);
                        }
                        Misc.ApplySelectionMask(this.target, selection, new Point(0, 0));
                    }
                }
                layer.RemoveBitmapEditMode();
                canvas.UpdateAfterEdit();
                history.Commit();
            }
            return;
        }// end function

        private function FillAll() : void
        {
            var _loc_1:int = 0;
            var _loc_2:int = 0;
            var _loc_3:int = 0;
            var _loc_4:int = 0;
            var _loc_5:* = this.target.height;
            while (_loc_4 < _loc_5)
            {
                
                _loc_2 = 0;
                _loc_3 = this.target.width;
                while (_loc_2 < _loc_3)
                {
                    
                    _loc_1 = this.Tolerate(_loc_2, _loc_4);
                    if (_loc_1 > 64)
                    {
                        if (_loc_1 > 128)
                        {
                            _loc_1 = 255;
                        }
                        this.target.setPixel32(_loc_2, _loc_4, _loc_1 << 24 | this.cr << 16 | this.cg << 8 | this.cb);
                    }
                    _loc_2++;
                }
                _loc_4++;
            }
            return;
        }// end function

        private function FloodFill(FillTool.as$362:int, FillTool.as$362:int) : void
        {
            var _loc_3:Range = null;
            var _loc_4:int = 0;
            var _loc_5:* = this.target.width;
            var _loc_6:* = this.target.height;
            this.cr = options.color >>> 16 & 255;
            this.cg = options.color >>> 8 & 255;
            this.cb = options.color & 255;
            this.ranges = new Vector.<Range>;
            this.pxchecked = new Vector.<Boolean>(_loc_5 * _loc_6, true);
            this.LinearFill(FillTool.as$362, FillTool.as$362, this.Tolerate(FillTool.as$362, FillTool.as$362));
            while (this.ranges.length > 0)
            {
                
                _loc_3 = this.ranges.shift();
                _loc_4 = _loc_3.start;
                while (_loc_4 <= _loc_3.stop)
                {
                    
                    if (_loc_3.row > 0 && !this.pxchecked[(_loc_3.row - 1) * _loc_5 + _loc_4])
                    {
                        this.LinearFill(_loc_4, (_loc_3.row - 1), this.Tolerate(_loc_4, (_loc_3.row - 1)));
                    }
                    if (_loc_3.row < (_loc_6 - 1) && !this.pxchecked[(_loc_3.row + 1) * _loc_5 + _loc_4])
                    {
                        this.LinearFill(_loc_4, (_loc_3.row + 1), this.Tolerate(_loc_4, (_loc_3.row + 1)));
                    }
                    _loc_4++;
                }
            }
            return;
        }// end function

        private function LinearFill(FillTool.as$362:int, FillTool.as$362:int, FillTool.as$362:int) : void
        {
            var _loc_4:int = 0;
            var _loc_5:int = 0;
            var _loc_6:Range = null;
            var _loc_7:* = this.target.width;
            this.pxchecked[_loc_7 * FillTool.as$362 + FillTool.as$362] = true;
            if (FillTool.as$362 > 5)
            {
                if (FillTool.as$362 > 160)
                {
                    FillTool.as$362 = 255;
                }
                this.target.setPixel32(FillTool.as$362, FillTool.as$362, FillTool.as$362 << 24 | this.cr << 16 | this.cg << 8 | this.cb);
            }
            if (FillTool.as$362 > 64)
            {
                _loc_4 = FillTool.as$362 - 1;
                _loc_5 = FillTool.as$362 + 1;
                while (_loc_4 >= 0 && !this.pxchecked[_loc_7 * FillTool.as$362 + _loc_4] && FillTool.as$362 > 64)
                {
                    
                    this.pxchecked[_loc_7 * FillTool.as$362 + _loc_4] = true;
                    FillTool.as$362 = this.Tolerate(_loc_4, FillTool.as$362);
                    if (FillTool.as$362 > 5)
                    {
                        if (FillTool.as$362 > 160)
                        {
                            FillTool.as$362 = 255;
                        }
                        this.target.setPixel32(_loc_4, FillTool.as$362, FillTool.as$362 << 24 | this.cr << 16 | this.cg << 8 | this.cb);
                    }
                    _loc_4 = _loc_4 - 1;
                }
                FillTool.as$362 = 255;
                while (_loc_5 < _loc_7 && !this.pxchecked[_loc_7 * FillTool.as$362 + _loc_5] && FillTool.as$362 > 64)
                {
                    
                    this.pxchecked[_loc_7 * FillTool.as$362 + _loc_5] = true;
                    FillTool.as$362 = this.Tolerate(_loc_5, FillTool.as$362);
                    if (FillTool.as$362 > 5)
                    {
                        if (FillTool.as$362 > 160)
                        {
                            FillTool.as$362 = 255;
                        }
                        this.target.setPixel32(_loc_5, FillTool.as$362, FillTool.as$362 << 24 | this.cr << 16 | this.cg << 8 | this.cb);
                    }
                    _loc_5++;
                }
                _loc_6 = new Range((_loc_4 + 1), (_loc_5 - 1), FillTool.as$362);
                this.ranges.push(_loc_6);
            }
            return;
        }// end function

        private function Tolerate(core.drawing:FillTool/MouseDown:int, core.drawing:FillTool/MouseDown:int) : int
        {
            this.px = this.source.getPixel32(core.drawing:FillTool/MouseDown - this.soffset.x, core.drawing:FillTool/MouseDown - this.soffset.y);
            this.max = 0;
            this.a = this.px >>> 24 & 255;
            this.a = this.ta - this.a;
            this.diff = this.a < 0 ? (-this.a) : (this.a);
            if (this.diff > this.max)
            {
                this.max = this.diff;
            }
            if (this.ta > 0)
            {
                this.r = this.px >>> 16 & 255;
                this.g = this.px >>> 8 & 255;
                this.b = this.px & 255;
                this.r = this.tr - this.r;
                this.diff = this.r < 0 ? (-this.r) : (this.r);
                if (this.diff > this.max)
                {
                    this.max = this.diff;
                }
                this.g = this.tg - this.g;
                this.diff = this.g < 0 ? (-this.g) : (this.g);
                if (this.diff > this.max)
                {
                    this.max = this.diff;
                }
                this.b = this.tb - this.b;
                this.diff = this.b < 0 ? (-this.b) : (this.b);
                if (this.diff > this.max)
                {
                    this.max = this.diff;
                }
            }
            if (options.antialias && options.tolerance > 0)
            {
                this.aa = 1.5 - this.max / options.tolerance;
                if (this.aa <= 0)
                {
                    return 0;
                }
                if (this.aa < 0.5)
                {
                    return int(this.aa * 512);
                }
                return 255;
            }
            if (this.max > options.tolerance)
            {
                return 0;
            }
            return 255;
        }// end function

    }
}
